#region Copyright (c) 2006 Jonathan Nauman
/*       _\|/_
         (o o)
+-----oOO-{_}-OOo-----------------------+
| Copyright (c) Jonathan Naumann        |
+---------------------------------------+
| 
| File: MonoPad.GladeGUI.cs
| Version:	0.7.3
+
*/
#endregion

//#define __DEBUG

using System;
using System.Collections.Generic;
using Gtk;
using GtkSourceView;
using Glade;
using System.IO;

namespace MonoPad {
	///
	/// Class GladeApp
	///
	public class GladeGUI {
		private List<string> list = new List<string>();
		private List<GtkSourceView.SourceView> views = new List<GtkSourceView.SourceView>();
		private string currentbuffer = "";
		
		private ConfigProvider cnfload = null;
		private ConfigContainer config = null;
		private FileContainer fc = new FileContainer();
		private InterfaceLogic il = new InterfaceLogic();
		private Glade.XML oGXML = null;
		
		protected GtkSourceView.SourceView oCode = null;
		
		// Glade MenuItems
		[Glade.Widget]
		MenuItem mnuView;
		
		[Glade.Widget]
		ImageMenuItem mnuCut;
		
		[Glade.Widget]
		ImageMenuItem mnuCopy;
		
		[Glade.Widget]
		ImageMenuItem mnuPaste;
		
		[Glade.Widget]
		ImageMenuItem mnuDelete;
		
		[Glade.Widget]
		ImageMenuItem mnuClose;
		
		[Glade.Widget]
		ImageMenuItem mnuNew;
		
		[Glade.Widget]
		ImageMenuItem mnuSave;
		
		[Glade.Widget]
		ImageMenuItem mnuSaveAs;
		
		[Glade.Widget]
		Notebook noteTab;
		
		[Glade.Widget]
		Label lblFilename;
		
		[Glade.Widget]
		ToolButton tbSave;
		
		[Glade.Widget]
		ToolButton tbClose;
		
		[Glade.Widget]
		Window editWindow;
		
		[Glade.Widget]
		Statusbar stateBar;
		
		///
		/// Default Constructor
		///
		public GladeGUI(string[] args) {
			string Options = "";
			
			if(args.Length == 0) {
				Options = "";
			}
			else {
				Options = args[0];
			}
			
			oGXML = new Glade.XML(null, "gui.glade", "editWindow", null);
			oGXML.Autoconnect(this);
			
			// config
			cnfload = new ConfigProvider();
			config = cnfload.GetConfiguration();
			
			// widget settings
			mnuView.Visible = false;
			mnuCut.State = StateType.Insensitive;
			mnuCopy.State = StateType.Insensitive;
			mnuPaste.State = StateType.Insensitive;
			mnuDelete.State = StateType.Insensitive;
			//mnuSave.State = StateType.Insensitive;
			//tbSave.State = StateType.Insensitive;
			
			// text view widget
			oCode = new GtkSourceView.SourceView();
			oCode.Buffer.Changed += new EventHandler(OnSourceViewChanged);
			
			if(config.LineNumbers) {
				oCode.ShowLineNumbers = true;
			}
			
			if(config.MonotypeFont) {
				Pango.FontDescription font = new Pango.FontDescription();
				font.Family = "Monospace";
				oCode.ModifyFont(font);
			}
			
			//Gtk.Style s = new Gtk.Style();
			//oCode.Style = s;
			oCode.TabsWidth = config.TabWidth;
			
			ScrolledWindow sw = new ScrolledWindow();
			sw.AddWithViewport(oCode);
			
			if(Options == "") {
				noteTab.RemovePage(noteTab.CurrentPage);
				noteTab.AppendPage(sw, new Label("NewFile.cs"));
				
				stateBar.Pop(0);
				stateBar.Push(0, "NewFile.cs");
				
				views.Add(oCode);
				list.Add("");
				
				noteTab.ShowAll();
				noteTab.NextPage();
			}
			else {
				this._ActionLoadFile(Options);
			}
		}
		
		// ------------------------------------
		// Menu events
		// ------------------------------------
		
		///
		/// Event for the copy menuitem
		///
		private void on_mnuCopy_activate(object o, EventArgs args) {
			//oCode.Buffer.AddSelectionClipboard
			//views[noteTab.CurrentPage].Buffer.AddSelectionClipboard();
		}
		
		///
		/// Event for the preferences menuitem
		///
		private void on_mnuPreferences_activate(object o, EventArgs args) {
			this._ActionPreferences();
		}
		
		///
		/// Event for the open menuitem
		///
		private void on_mnuOpen_activate(object o, EventArgs args) {
			this._ActionOpen();
		}
		
		///
		/// Event for the save menuitem
		///
		private void on_mnuSave_activate(object o, EventArgs args) {
			this._ActionSave();
		}
		
		///
		/// Event for the save-as menuitem
		///
		private void on_mnuSaveAs_activate(object o, EventArgs args) {
			this._ActionSaveAs();
		}
		
		///
		/// Event : on_mnuNew_activate(object o, EventArgs args)
		///
		private void on_mnuNew_activate(object o, EventArgs args) {
			list.Add("");
			il.ActionNew(noteTab, config, ref views);
		}
		
		///
		/// Event for teh close menuitem
		///
		private void on_mnuClose_activate(object o, EventArgs args) {
			this.currentbuffer = this._GetCurrentBuffer();
			
			il.ActionExit(
				ref editWindow, 
				this.currentbuffer, 
				( this.noteTab.CurrentPage == -1 ? "" : list[this.noteTab.CurrentPage] )
			);
		}
		
		///
		/// Event for the info menuitem
		///
		private void on_mnuInfo_activate(object o, EventArgs args) {
			new AboutBox();
		}
		
		// ------------------------------------
		// Toolbar events
		// ------------------------------------
		
		///
		/// Event for the notetab
		///
		private void on_button_press_event(object o, ButtonPressEventArgs args) {
			list.Add("");
			il.ActionNew(noteTab, config, ref views);
		}
		
		///
		/// Event for the open button
		///
		private void on_tbOpen_clicked(object o, EventArgs args) {
			this._ActionOpen();
		}
		
		///
		/// Event for the save button
		///
		private void on_tbSave_clicked(object o, EventArgs args) {
			this._ActionSave();
		}
		
		///
		/// Event for the new button
		///
		private void on_tbNew_clicked(object o, EventArgs args) {
			list.Add("");
			il.ActionNew(noteTab, config, ref views);
		}
		
		///
		/// Event for the ecit button
		///
		private void on_tbExit_clicked(object o, EventArgs args) {
			this.currentbuffer = this._GetCurrentBuffer();
			
			il.ActionExit(
				ref editWindow, 
				currentbuffer, 
				( this.noteTab.CurrentPage == -1 ? "" : list[this.noteTab.CurrentPage] )
			);
		}
		
		///
		/// Event for the preferences button
		///
		private void on_tbPreferences_clicked(object o, EventArgs args) {
			this._ActionPreferences();
		}
		
		///
		/// Event for the close button
		///
		private void on_tbClose_clicked(object o, EventArgs args) {
			this.currentbuffer = this._GetCurrentBuffer();
			
			if(this.noteTab.NPages > 0) {
				int closedPage = il.ActionCloseTab(
					ref this.editWindow, 
					this.currentbuffer, 
					( this.noteTab.CurrentPage == -1 ? "" : list[this.noteTab.CurrentPage] ), 
					ref this.noteTab
				);
				
				if(closedPage != -1) {
					#if __DEBUG
						Console.WriteLine("tab -> " + noteTab.CurrentPage.ToString());
						Console.WriteLine("list -> " + list.Count.ToString());
					#endif
					
					views.RemoveAt(closedPage);
					list.RemoveAt(closedPage);
				}
			}
		}
		
		// ------------------------------------
		// Additional events
		// ------------------------------------
		
		///
		/// Event for the page switch event
		///
		private void on_switch_page(object o, SwitchPageArgs args) {
			//GtkSourceView.SourceView code = (GtkSourceView.SourceView)this.noteTab.CurrentPageWidget;
			
			if(noteTab.CurrentPage != -1 && views.Count != -1 && views.Count > noteTab.CurrentPage) {
				this.currentbuffer = "";
				this.currentbuffer = views[noteTab.CurrentPage].Buffer.Text;
				
				Label lblFile = (Label)noteTab.GetTabLabel(noteTab.CurrentPageWidget);
				
				stateBar.Pop(0);
				stateBar.Push(
					0, 
					lblFile.Name + " - Lines: " + views[noteTab.CurrentPage].Buffer.LineCount.ToString()
				);
				
				Console.WriteLine("tab name -> " + lblFile.Name);
				
				#if __DEBUG
					Console.WriteLine("tab -> " + noteTab.CurrentPage.ToString());
					Console.WriteLine("views -> " + views.Count.ToString());
					Console.WriteLine("buffer -> " + views[noteTab.CurrentPage].Buffer.Text);
					//Console.WriteLine("CURRENT BUFFER: " + this.currentbuffer);
				#endif
			}
		}
		
		///
		/// Event for the window close button
		///
		private void on_editWindow_destroy(object o, DestroyEventArgs args) {
			il.ActionExit(
				ref editWindow, 
				this.currentbuffer, 
				( this.noteTab.CurrentPage == -1 ? "" : list[this.noteTab.CurrentPage] )
			);
		}
		
		///
		/// Event for the window close button
		///
		private void on_editWindow_object_destroy(object o, EventArgs args) {
			il.ActionExit(
				ref editWindow, 
				this.currentbuffer, 
				( this.noteTab.CurrentPage == -1 ? "" : list[this.noteTab.CurrentPage] )
			);
		}
		
		///
		/// Event for the change event
		///
		private void OnSourceViewChanged(object o, EventArgs args) {
			this.currentbuffer = "";
			this.currentbuffer = this._GetCurrentBuffer();
			Label lblFile = this._GetCurrentTabLabel();
			
			//mnuSave.State = StateType.Normal;
			//tbSave.State = StateType.Normal;
			
			// reload filename
			int iPos = fc.Filename.LastIndexOf("/");
			
			lblFile.Text = fc.Filename.Substring(iPos + 1) + " *";
			lblFile.Name = fc.Filename;
			
			noteTab.SetTabLabel(noteTab.CurrentPageWidget, lblFile);
			
			stateBar.Pop(0);
			stateBar.Push(
				0, 
				lblFile.Name + " - Lines: " + views[noteTab.CurrentPage].Buffer.LineCount.ToString()
			);
		}
		
		// ------------------------------------
		// Methods
		// ------------------------------------
		
		///
		/// Get the current notetab buffer
		///
		private string _GetCurrentBuffer() {
			if(this.noteTab.NPages > 0) {
				return views[noteTab.CurrentPage].Buffer.Text;
			}
			else {
				return "";
			}
		}
		
		///
		/// Get the current tab label
		///
		private Label _GetCurrentTabLabel() {
			return (Label)noteTab.GetTabLabel(noteTab.CurrentPageWidget);
		}
		
		///
		/// Action method for open files
		///
		private void _ActionOpen() {
			bool canAdd = true;
			string mime = il.ActionOpen(ref fc, ref editWindow);
			
			if(fc.Filestream != null && fc.Filename.Trim() != "") {
				if(noteTab.NPages == 1) {
					if(this.currentbuffer == "") {
						canAdd = false;
					}
				}
				
				if(canAdd) {
					il.ActionNew(noteTab, config);
				}
				
				this._LoadStreamToTextView(mime);
			}
		}
		
		///
		/// Load a file by name
		///
		private void _ActionLoadFile(string Filename) {
			FileInfo info = new FileInfo(Filename);
			
			fc.Filename = Filename;
			fc.Filestream = File.OpenRead(info.FullName);
			
			string mime = il.GetMimetype(info.Extension);
			
			#if __DEBUG
				Console.WriteLine("Open file: " + info.FullName);
			#endif
			
			if(fc.Filestream != null && fc.Filename.Trim() != "") {
				this._LoadStreamToTextView(mime);
			}
		}
		
		///
		/// Loads the stream to the textview
		///
		private void _LoadStreamToTextView(string mimetype) {
			try {
				StreamReader srInput = new StreamReader(fc.Filestream);
				
				int iPos = fc.Filename.LastIndexOf("/");
				
				Label lblFile = (Label)noteTab.GetTabLabel(noteTab.CurrentPageWidget);
				lblFile.Text = fc.Filename.Substring(iPos + 1);
				
				// Gtk SourceView
				GtkSourceView.SourceLanguagesManager oSLM = new GtkSourceView.SourceLanguagesManager();
				//oSLM.LangFilesDirs.Append("/usr/share/gtksourceview-1.0/language-specs/csharp.lang");
				
				GtkSourceView.SourceLanguage oLang;
				
				try {
					if(mimetype == "text/plain") {
						oLang = oSLM.GetLanguageFromMimeType("text/x-changelog");
					}
					else {
						oLang = oSLM.GetLanguageFromMimeType(mimetype);
					}
					
					#if __DEBUG
						Console.WriteLine("Language: " + oLang.Name);
					#endif
				}
				catch(Exception ex) {
					oLang = oSLM.GetLanguageFromMimeType("text/x-changelog");
					
					#if __DEBUG
						Console.WriteLine("Language: " + oLang.Name);
					#endif
				}
				
				if(oLang != null) {
					GtkSourceView.SourceBuffer oBuffer = new GtkSourceView.SourceBuffer(oLang);
					oBuffer.Highlight = true;
					
					oBuffer.SetText(srInput.ReadToEnd());
					//oBuffer.Text = srInput.ReadToEnd();
					
					#if __DEBUG
						Console.WriteLine("oBuffer.Text: " + oBuffer.Text);
					#endif
					
					oCode = new GtkSourceView.SourceView(oBuffer);
					
					// set your own tag styles if you like - the descriptions have ASCII
					// characters surrounded by "@"
					// non-alpha characters
					/*
					SourceTagStyle sts = oLang.GetTagStyle("C@43@@43@@32@Line@32@Comment");
					sts.Italic = true;
					sts.Foreground = new Gdk.Color(255, 0, 0);
					oLang.SetTagStyle("C@43@@43@@32@Line@32@Comment", sts);
					*/
					
					if(config.LineNumbers) {
						oCode.ShowLineNumbers = true;
					}
				
					if(config.MonotypeFont) {
						Pango.FontDescription font = new Pango.FontDescription();
						font.Family = "Monospace";
						oCode.ModifyFont(font);
					}
					
					//oBuffer.LineCount
				}
				else {
					oCode = new GtkSourceView.SourceView();
					
					if(config.LineNumbers) {
						oCode.ShowLineNumbers = true;
					}
					
					if(config.MonotypeFont) {
						Pango.FontDescription font = new Pango.FontDescription();
						font.Family = "Monospace";
						oCode.ModifyFont(font);
					}
				}
				
				oCode.Buffer.Changed += new EventHandler(OnSourceViewChanged);
				
				this.currentbuffer = oCode.Buffer.Text;
				
				ScrolledWindow sw = new ScrolledWindow();
				sw.AddWithViewport(oCode);
				
				if(noteTab.NPages == 1 && views.Count == 1 && this._GetCurrentBuffer() == "") {
					views.RemoveAt(0);
				}
				
				lblFile.Name = fc.Filename;
				noteTab.RemovePage(noteTab.CurrentPage);
				noteTab.AppendPage(sw, lblFile);
				//noteTab.SetMenuLabelText();
				
				stateBar.Pop(0);
				stateBar.Push(0, fc.Filename);
				
				views.Add(oCode);
				list.Add(this.currentbuffer);
				
				#if __DEBUG
					foreach(GtkSourceView.SourceView gs in views) {
						Console.WriteLine("Buffer: " + gs.Buffer.Text);
					}
				#endif
				
				noteTab.ShowAll();
				noteTab.NextPage();
				
				fc.Filestream.Close();
				srInput.Close();
			}
			catch(Exception ex) {
				Console.WriteLine("---------------------------------------------");
				Console.WriteLine("ERROR");
				Console.WriteLine("StackTrace: " + ex.StackTrace);
				Console.WriteLine("Message: " + ex.Message);
				Console.WriteLine("---------------------------------------------");
			}
		}
		
		///
		/// Action method for save file
		///
		private void _ActionSave() {
			this.currentbuffer = "";
			this.currentbuffer = this._GetCurrentBuffer();
			
			Label lblFile = (Label)noteTab.GetTabLabel(noteTab.CurrentPageWidget);
			
			il.ActionSave(this.currentbuffer, lblFile.Name);
			
			// reload filename
			int iPos = fc.Filename.LastIndexOf("/");
			
			lblFile.Text = fc.Filename.Substring(iPos + 1);
			lblFile.Name = fc.Filename;
			
			noteTab.SetTabLabel(noteTab.CurrentPageWidget, lblFile);
			
			stateBar.Pop(0);
			stateBar.Push(
				0, 
				fc.Filename + " - Lines: " + views[noteTab.CurrentPage].Buffer.LineCount.ToString()
			);
			
			//tbSave.State = StateType.Normal;
			mnuSave.State = StateType.Normal;
		}
		
		///
		/// Action method for save file as
		///
		private void _ActionSaveAs() {
			this.currentbuffer = "";
			this.currentbuffer = this._GetCurrentBuffer();
			
			Label lblFile = (Label)noteTab.GetTabLabel(noteTab.CurrentPageWidget);
			
			fc.Filename = lblFile.Name;
			
			il.ActionSaveAs(this.currentbuffer, ref fc);
			
			// reload filename
			int iPos = fc.Filename.LastIndexOf("/");
			
			lblFile.Text = fc.Filename.Substring(iPos + 1);
			lblFile.Name = fc.Filename;
			
			noteTab.SetTabLabel(noteTab.CurrentPageWidget, lblFile);
			
			stateBar.Pop(0);
			stateBar.Push(
				0, 
				fc.Filename + " - Lines: " + views[noteTab.CurrentPage].Buffer.LineCount.ToString()
			);
		}
		
		///
		/// Action mezhod for the preferences dialog
		///
		private void _ActionPreferences() {
			new Preferences();
		}
	}
}
